import * as THREE from "three";

function setDissolveShader(shader: any, params: any, type = 1) {
  const _types = [
    function _type0(shader: any) {
      setCommon(shader, params);

      // shader main
      shader.fragmentShader = shader.fragmentShader.replace(
        "#include <dithering_fragment>",
        /* glsl */ `
          #include <dithering_fragment>
          float noiseValue = texture2D(noiseTexture, xUv).r;
          vec4 finalColor = linearToOutputTexel( vec4(edgeColor, gl_FragColor.a) );
          if(noiseValue > dissolveProgress)
          {
              discard;
          }
          
          if(noiseValue + edgeWidth > dissolveProgress){
              gl_FragColor = vec4(finalColor.rgb, 1.0);
          }
      `
      );
    },

    function _type1(shader: any) {
      setCommon(shader, params);

      // shader main
      shader.fragmentShader = shader.fragmentShader.replace(
        "#include <dithering_fragment>",
        /* glsl */ `
          #include <dithering_fragment>
          float noiseValue = texture2D(noiseTexture, xUv).r;
          
          vec4 finalColor = texture2D(edgeColorTexture, xUv);
          // vec4 finalColor = linearToOutputTexel( vec4(edgeColor, gl_FragColor.a) );

          float alpha = step(noiseValue - edgeWidth, dissolveProgress);
          gl_FragColor.a = alpha;

          float useOrigin = step(noiseValue, dissolveProgress);
          gl_FragColor.rgb = mix(finalColor.rgb, gl_FragColor.rgb, useOrigin);

      `
      );
    },
  ];

  function setCommon(shader: any, params: any) {
    shader.uniforms.edgeColor = { value: new THREE.Color(params.edgeColor) };
    shader.uniforms.edgeWidth = { value: params.edgeWidth };
    shader.uniforms.dissolveSpeed = { value: params.dissolveSpeed };
    shader.uniforms.dissolveProgress = { value: params.dissolveProgress };
    shader.uniforms.noiseTexture = { value: params.noiseTexture };
    shader.uniforms.edgeColorTexture = { value: params.edgeColorTexture };

    shader.vertexShader = shader.vertexShader.replace(
      "#include <common>",
      ["varying vec2 xUv;", "#include <common>"].join("\n")
    );

    shader.vertexShader = shader.vertexShader.replace(
      "#include <uv_vertex>",
      ["xUv = uv;", "#include <uv_vertex>"].join("\n")
    );

    // shader headers
    shader.fragmentShader = shader.fragmentShader.replace(
      "#include <common>",
      /* glsl */ `
      #include <common>
      uniform float dissolveProgress;
      uniform float edgeWidth;
      uniform vec3 edgeColor;
      uniform sampler2D noiseTexture;
      uniform sampler2D edgeColorTexture;
      varying vec2 xUv;
  `
    );
  }

  _types[type](shader);
}

export { setDissolveShader };
